The present invention relates to computer systems and more particularly to a method for managing memory in a run-time environment.
A dynamic run-time environment for a language, such as JAVA(trademark), is responsible for managing memory for objects that are created and destroyed during the execution of a program. An object is an entity that encapsulates data and, in some languages, operations associated with the object. Since the encapsulated data is stored in memory, objects are associated with particular regions of memory that are allocated and deallocated by the dynamic run-time environment.
The state of a program, or xe2x80x9cprogram state,xe2x80x9d is the set of the objects and the references between the objects that exist at a specific point in time during the execution of the program. A xe2x80x9creferencexe2x80x9d is used by a run-time environment to identify and ultimately access the region of memory for storing the data of the object. Typically, references between objects in a run-time environment are encoded using machine pointers. A machine pointer is an instance of a native type that contains the address of the object in the main memory, which can be a real memory address or, more commonly, a virtual address on a machine that implements a virtual memory system.
One popular run-time environment is a JAVA(trademark) programming language virtual machine, which supports a platform-independent, object-oriented language developed by Sun Microsystems. In the JAVA(trademark) programming language, the attributes and methods for a class of objects are typically defined in a source file, which is compiled into an architecture-neutral object file containing bytecodes that are interpreted in the virtual machine at the target platform. It is common for objects to reference other objects.
Lately, there has been much interest in using the JAVA(trademark) programming language in a multi-user environment that allows multiple users to connect in separate, concurrent sessions to a server system, such as a relational database system. When designing a run-time environment for such a multi-user environment, scalability in terms of the number of simultaneous users who can establish separate sessions is very important. A significant constraint for user scalability is the size of the memory footprint that each session consumes. For example, a server system may have 100 megabytes (Mb) of memory for supporting all the user sessions. If the session memory footprint is 1 Mb, then only 100 users can be supported at one time. Therefore, it is desirable to reduce the session memory footprint to improve scalability.
One approach for reducing the session memory footprint is to provide a shorter duration memory named xe2x80x9ccall memoryxe2x80x9d that is active for the duration of a xe2x80x9ccallxe2x80x9d but automatically deallocated when the call terminates. A call is the period of time when the user is actively using the server, such as during execution of a Structured Query Language (SQL) statement in a database server. Accordingly, those objects that do not need to live beyond the duration of the call are placed in the call memory rather than session memory. When the call is completed, objects in the call memory are deallocated and the call-duration memory is reclaimed for use. This approach has been implemented in Oracle Corporation""s PL/SQL language, for instance, in which objects are explicitly declared as having the duration of a call or of a session. Memory management in such a language is straightforward because the objects are simply allocated in the memory that corresponds to their duration.
The JAVA(trademark) programming language, however, defines the lifetime of many objects, especially system objects, to extend throughout the duration of a session and does not have the notion of a call or call duration in the programming model. Therefore, the run-time environment mush have a policy for using call memory. Accordingly, one approach is to simply ignore the provision of the call memory by the multi-user system and allocate every object in session memory, but this approach suffers from scalability because short-lived objects are unnecessarily allocated in session memory.
Another approach is to allocate objects first in the shorter-duration call memory, and then, at the time the call terminates, migrate the objects into the longer duration session memory. In this approach, session memory is consumed only if the object is still alive at the end of the call. The JAVA(trademark) programming language, however, imposes restrictions on this approach by requiring several system classes to store large objects in static class variables. Use of static class variables is also common in user code. In many cases, the state of the these objects is no longer relevant after the call, but they are still considered alive at the end of the call. Therefore, the above-described migration policy causes these large objects to be migrated into session memory even though the state of the large object is no longer relevant, thereby increasing session memoryrequirements per session and reducing scalability.
For example, the standard input, output, and error streams maintain large print buffers that merely reserve space for temporary use by the streams. Typically, when the call terminates the print buffers are flushed so that no meaningful information remains in the buffer. However, the print buffer itself is still a live object, being referenced by its stream class. Therefore, the migration process of copying a stream object at the end of the call to session memory forces the copying of a large, but essentially empty object into session space.
In this example, there is a problem if the user directly attempts to reduce the session memory consumed by these objects by unreferencing the print buffer before the end of the call. Unreferencing an object causes the garbage collector to deallocate the object at the end of the call. If the print buffer was unreferenced, the print buffer would not available for use in the finalization of other garbage collected objects at the end of call. Some objects, for example, will print an error message using a stream in their finalization code, which is called when the objects are garbage collected. In this scenario, at worst, the null print buffer would cause a run-time error or exception, and, at best, the print buffer would be reallocated. In the latter case, the print buffer is still alive at the end of call and is therefore migrated to session memory, thereby defeating the purpose of the user""s direct attempt to reduce the session memory usage.
The space used by such objects is substantial, on the order of 150 kilobytes (Kb) for a JAVA(trademark) programming language xe2x80x9cHello Worldxe2x80x9d program, thereby seriously affecting the scalability of the system. Therefore, there is a need for improving the scalability of such run-time environments.
The related, commonly-assigned, co-pending U.S. patent application Ser. No. 09/512,619 entitled xe2x80x9cMethod For Managing Memory Using Explicit, Lazy Initialization In A Run-Time Environmentxe2x80x9d discloses a mechanism for registering a routine to deinitialize the large object in a static class variable at the end of call (e.g. by setting the class variable to null to unreference the large object), which prevents the large object from being migrated into session memory. This routine is called after the finalization of garbage collected objects that may use the large object. In a subsequent call, explicit, lazy initialization is used, in which the large object is checked before use and re-initialized if the large object was still deallocated.
Because the lazy initialization is explicit, all the users of the static class variable have to respect the programming model that the static class variable has to be first checked before its use. While this approach is effective for user code and for the private static class variables of a JAVA(trademark) programming language system class, it is not so suitable for public static class variables of JAVA(trademark) programming language system classes, because users of these public static class variables do not expect these variables to become uninitialized. As a result, large amounts of user code would have to retrofit to explicitly check to determine if the public static class variables need to be re-initialized. Therefore, there is a need for reducing the session memory consumed by such public static class variables without requiring pre-existing user code to be retrofitted.
These and other needs are addressed by the present invention, by providing for activation-based initialization for such public class variables. In an activation-based initialization approach, pointers to objects such as public static class variables are replaced with external references such as those described in the related, commonly-assigned, co-pending U.S. patent application Ser. No. 09/408,847, entitled xe2x80x9cA Method and Article for Managing References to External Objects in a Run-Time Environment.xe2x80x9d
In accordance with this approach, an external reference to an object encodes an index that is used to find corresponding entries in a value array and a descriptor array. The corresponding entry in the value array is null the first time the object is accessed through the external reference. The corresponding entry in the descriptor array provides instructions and arguments for realizing the object, for example, by allocating and initializing memory or by finding a globally shared object as appropriate. The descriptor is evaluated when the corresponding entry in the value array is null and returns a pointer to the realized object. Furthermore, the instructions that realize the object also register an end-of-call routine to deactivate the object at the end of the call, for example, by setting the corresponding entry in the value array to null. This action unreferences the allocated space for the object, thereby preventing its migration into session memory.
One embodiment of the invention is a method and software for managing memory in a run-time environment, in which an object is activated by initializing the object and registering a routine to deactivate the object at an end of a call. At the end of the call, the routine to deactivate the object is executed, preferably after finalization of non-live object during garbage collection. As a result, the object is not migrated into session memory.
Another embodiment pertains to a method and software for managing memory in a run-time environment. A object is accessed by means of an external reference by: extracting an index from the external reference, fetching a pointer value from an entry in a value array at a position indicated by the index, and if the pointer value is a null value, then fetching a descriptor from an entry in a descriptor array at a position indicated by the index, initializing the object based on the descriptor, and registering a routine to deactivate the object at an end of call. At the end of the call, the routine to deactivate the object is executed, for instance, by setting the entry in the value array at the position indicated by the index to null.
Still other objects and advantages of the present invention will become readily apparent from the following detailed description, simply by way of illustration of the best mode contemplated of carrying out the invention. As will be realized, the invention is capable of other and different embodiments, and its several details are capable of modifications in various obvious respects, all without departing from the invention. Accordingly, the drawing and description are to be regarded as illustrative in nature, and not as restrictive.